package controllers

import (
	"github.com/gin-gonic/gin"
	"github.com/tommy351/gin-sessions"
	"strconv"
	"strings"
	"time"
	"wallet/models"
)

type JSONResult struct {
	Common     float32        //公共开销
	SumDate    time.Time      // 统计时间
	Month      string         //统计月份
	Extras     []*Extra       // 非公共开支
	UserName   string         //用户名
	UserID     uint           //用户id
	Total      float32        //当月总共产生的费用
	Pay        float32        //自己实际支出
	NeedPay    float32        //需要补交的费用
	NoEnough   []*models.Bill // 少人吃饭的账单
	ExtraCount int            //额外信息数量
	Loaded     bool
}

type Extra struct {
	Value      float32   //费用
	Remark     string    //说明
	OccureDate time.Time //发生时间
}

func AddBook(c *gin.Context) {

	name := c.PostForm("name")
	description := c.PostForm("description")

	book := models.InsertBook(name, description, 12, 0)
	if book.ID > 0 {
		if models.InsertUserBook(book.UserID, book.ID) {

		} else {
			//回滚
		}
	}
}

func AddUserBook(c *gin.Context) {
	bookid := c.Query("bookid")
	uid := c.Query("uid")
	if len(bookid) == 0 || len(uid) == 0 {
		c.JSON(200, gin.H{
			"message": "error parameter.",
		})
	} else {
		book_id, err := strconv.Atoi(bookid)
		if err != nil {
			c.JSON(200, gin.H{
				"message": err.Error(),
			})
		}
		user_id, err := strconv.Atoi(uid)
		if err != nil {
			c.JSON(200, gin.H{
				"message": err.Error(),
			})
		}
		if models.InsertUserBook(uint(user_id), uint(book_id)) {

		} else {

		}
	}
}

func SelectBookList(c *gin.Context) {
	s := sessions.Get(c)
	user := s.Get("current_user")
	//fmt.Println(user)
	if value, ok := user.(*models.User); ok {
		books, err := models.SelectBookListByUserID(value.ID)
		bookc := make(map[uint]int)
		for _, book := range books {
			bookc[book.ID] = models.CountUserByBookID(book.ID)
		}
		if err == nil {
			c.JSON(200, gin.H{
				"data":  books,
				"extra": bookc,
			})
		} else {
			c.JSON(200, gin.H{
				"message": err.Error(),
			})
		}

	} else {
		//fmt.Println("convert interface{} to user failed.")
	}
}

func Cash(c *gin.Context) {

	bookId := c.Query("bookid")
	start := c.Query("start")
	end := c.Query("end")
	month := c.Query("month")
	if len(month) == 0 {
		month = time.Now().Format("2006-01")
	}
	_bookId, _ := strconv.ParseInt(bookId, 10, 8)

	/*
		userbooks := models.SelectUserBookByBookID(uint(_bookId))
		if len(userbooks) == 0 {
			c.JSON(200, gin.H{
				"message": "the book doesn't have any menmber.",
			})
			return nil
		}

		results := make(map[uint]*JSONResult)

		// 先计算所有人参加的账目
		length := len(userbooks)

		common := models.SumBill(uint(_bookId), length, month)
		per := common / float32(length)

		for _, ub := range userbooks {
			user := models.GetUserByID(ub.UserID)
			ret := JSONResult{
				Common:   per,
				SumDate:  time.Now(),
				Month:    month,
				UserName: user.NickName,
				UserID:   ub.UserID,
			}
			ret.Extras = make([]*Extra, 0)
			results[ub.UserID] = &ret
		}

		invitebills := models.SelectInviteBill(uint(_bookId), month)
		for _, invite := range invitebills {
			every := invite.Account / float32(invite.Total)
			uids := strings.Split(strings.Replace(invite.Participant, "$", "", -1), "#")
			for _, uid := range uids {
				if len(uid) > 0 {
					userid, _ := strconv.ParseInt(uid, 10, 8)
					extra := Extra{
						Remark:     invite.Remark,
						OccureDate: invite.OccureDate,
					}
					if uint(userid) == invite.InvitorID {
						// 因为字符串切割会多出来一个空字符串，然后加上自己消费的
						extra.Value = float32(int(invite.Total)-len(uids)+2) * every
					} else {
						extra.Value = every
					}
					results[uint(userid)].Extras = append(results[uint(userid)].Extras, &extra)
				}
			}
		}

		actualpay := models.SelectCasherCount(uint(_bookId), month)
		for _, actual := range actualpay {
			results[actual.CasherID].Pay = float32(actual.Account)
		}

		// 计算当月开销总数
		for _, ret := range results {
			ret.Total += ret.Common
			for _, extra := range ret.Extras {
				ret.Total += extra.Value
			}
			ret.NeedPay = ret.Total - ret.Pay
		}
	*/

	common, per, results := Calculate(uint(_bookId), month, start, end)
	c.JSON(200, gin.H{
		"common": common,
		"per":    per,
		"data":   results,
	})

}

func Calculate(_bookId uint, month, start, end string) (float32, float32, map[uint]*JSONResult) {
	userbooks := models.SelectUserBookByBookID(uint(_bookId))
	if len(userbooks) == 0 {
		return 0, 0, nil
	}

	results := make(map[uint]*JSONResult)

	// 先计算所有人参加的账目
	length := len(userbooks)

	common := models.SumBill(uint(_bookId), length, month, start, end)
	per := common / float32(length)

	for _, ub := range userbooks {
		user := models.GetUserByID(ub.UserID)
		ret := JSONResult{
			Common:   per,
			SumDate:  time.Now(),
			Month:    month,
			UserName: user.NickName,
			UserID:   ub.UserID,
		}
		ret.Extras = make([]*Extra, 0)
		ret.NoEnough = make([]*models.Bill, 0)
		results[ub.UserID] = &ret
	}

	// 计算少人吃饭的情况
	for i := length - 1; i > 1; i-- {
		notenoughbills := models.SelectBillListByTotal(_bookId, i, month, start, end)
		for _, notenough := range notenoughbills {
			//every := notenough.Account / float32(notenough.Total)
			uids := strings.Split(strings.Replace(notenough.Participant, "$", "", -1), "#")
			for _, uid := range uids {
				if len(uid) > 0 {
					userid, _ := strconv.ParseInt(uid, 10, 8)
					results[uint(userid)].NoEnough = append(results[uint(userid)].NoEnough, notenough)
				}
			}
		}
	}

	invitebills := models.SelectInviteBill(uint(_bookId), month, start, end)
	for _, invite := range invitebills {
		every := invite.Account / float32(invite.Total)
		uids := strings.Split(strings.Replace(invite.Participant, "$", "", -1), "#")
		for _, uid := range uids {
			if len(uid) > 0 {
				userid, _ := strconv.ParseInt(uid, 10, 8)
				extra := Extra{
					Remark:     invite.Remark,
					OccureDate: invite.OccureDate,
				}
				if uint(userid) == invite.InvitorID {
					// 因为字符串切割会多出来一个空字符串，然后加上自己消费的
					extra.Value = float32(int(invite.Total)-len(uids)+2) * every
				} else {
					extra.Value = every
				}
				results[uint(userid)].Extras = append(results[uint(userid)].Extras, &extra)
			}
		}
	}

	actualpay := models.SelectCasherCount(uint(_bookId), month, start, end)
	for _, actual := range actualpay {
		results[actual.CasherID].Pay = float32(actual.Account)
	}

	// 计算当月开销总数
	for _, ret := range results {
		ret.Total += ret.Common
		for _, extra := range ret.Extras {
			ret.Total += extra.Value
		}
		for _, notenough := range ret.NoEnough {
			avg := notenough.Account / float32(notenough.Total)
			ret.Total += avg
			notenough.Avg = avg
		}
		ret.ExtraCount = len(ret.Extras) + len(ret.NoEnough)
		ret.Loaded = len(ret.Extras) > 0
		ret.NeedPay = ret.Total - ret.Pay
	}
	return common, per, results
}
